<?php
/**
 * Created by PhpStorm.
 * User: zsf
 * Date: 2018/5/14
 * Time: 9:39
 */

namespace App\Services\Authorize;

use App\Models\Enterprise\Enterprise;
use App\Services\ResponseCode;
use App\Models\GroupSeat\Seat;
use App\Models\DeviceLine\PubAccount;
use App\Models\Enterprise\SuperEnterprise;
use Illuminate\Support\Str;

class SeatSignature extends BaseSignature implements AuthorizeInterface
{

    const SIGNATURE_HEADER_KEYS = ['seat', 'timestamp', 'source', 'auth-type', 'nonce'];

    protected $seat, $number, $outlineNumber;

    /**
     * @return Seat|null
     * @throws \App\Exceptions\ApiException
     * 获取当前用户
     */
    public function getUser(): ?Seat
    {
        $methods = get_class_methods($this);
        foreach ($methods as $method) {
            if (starts_with($method, '_validate')) {
                $this->$method();
            }
        }
        $this->verifyCaptcha();
        if (is_bs() && !request()->header('domain')) {
            api_exception(ResponseCode::DOMAIN_IS_MUST);
        }

        if (!request()->input('is_zibo')) {
            if (request()->input('is_ccgeid')) {
                $enterprise = Enterprise::find($this->outlineNumber);
                if (!$enterprise) {
                    api_exception(ResponseCode::ENTERPRISE_NOT_EXISTS);
                }
                $seid = $enterprise['seid'];
                $ccgeid = $enterprise['id'];
            } else {
                $pubAccount = PubAccount::where('outline_number', $this->outlineNumber)->first();
                if (!$pubAccount) {
                    api_exception(ResponseCode::PUB_ACCOUNT_ERROR);
                }
                $seid = $pubAccount['seid'];
                $ccgeid = $pubAccount['ccgeid'];
            }
        }

        // 判断登录域名与登录企业关系
        if (is_bs() && !request()->input('is_zibo')) {
            $this->domain = request()->header('domain');
            //私有化部署
            if (!is_ip($this->domain)) {
                $this->superEnterprise = SuperEnterprise::where('domain', $this->domain)->first();
                //如果根据域名未获取到超级企业，则显示非法二级域名登录时报错
            } else {
                $this->domain = get_ip_port();
                $this->superEnterprise = SuperEnterprise::where('domain', $this->domain)->first();
            }
            if (!$this->superEnterprise) {
                api_exception(ResponseCode::VALID_DOMAIN);
            }
            if ($this->superEnterprise['id'] !== $seid) {
                api_exception(ResponseCode::SWITCHNUMBER_NOT_EXISTS);
            }

        }
        if (request()->input('is_zibo')) {
            $this->seat = Seat::where('work_number', $this->number)->where('seid', env('ZIBO_SEID', 134))->first();
        } else {
            if (request()->input('login_type')) {
                $this->seat = Seat::where('work_number', $this->number)->where('ccgeid', $ccgeid)->where('seid', $seid)->first();
            } else {
                $this->seat = Seat::where('number', $this->number)->where('ccgeid', $ccgeid)->where('seid', $seid)->first();
            }
        }

        if (!$this->seat) {
            api_exception(ResponseCode::LOGIN_FAILED, '账号或密码错误');
        }
        if ('1' == data_get($this->seat, 'disabled')) {
            api_exception(ResponseCode::SEAT_DISABLED);
        }
        if ($this->validateSignature()) {
            return $this->seat;
        }
        return null;
    }

    /**
     * @throws \App\Exceptions\ApiException
     * 校验用户名是否符合格式
     */
    protected function _validateUsername(): void
    {
        if (request()->input('is_zibo')) {
            $this->number = request()->header('seat');
            return;
        }
        if (!request()->header('seat') || !Str::contains(request()->header('seat'), '@')) {
            api_exception(ResponseCode::SEAT_ERROR);
        }
        $array = explode('@', request()->header('seat'));
        $this->outlineNumber = $array[count($array) - 1];
        unset($array[count($array) - 1]);
        $this->number = implode('@', $array);
        if (!$this->number || !$this->outlineNumber) {
            api_exception(ResponseCode::SEAT_ERROR);
        }
    }

    /**
     * @return array
     * 获取参与签名的头部参数
     */
    protected function getSignatureHeadKeys(): array
    {
        return self::SIGNATURE_HEADER_KEYS;
    }

    /**
     * 获取签名密钥
     * @return mixed
     */
    protected function getSignatureKey(): ?string
    {
        return $this->seat['password'];
    }

}
